from time import gmtime, strftime
import time
import timeit
import logging

from Strategy.config import CONFIG, STATIC

from MarketData.account import Account
from MarketData.const import CONST

from Strategy.account import Account_std, tieAccount_trade, tieAccount_withdraw, update_Account_fromOrder
from Strategy.model import evaluation, filter_Profit
from Strategy.quote import Quote_multithread, summarize_Quote, Quote_multithread_mid
from Strategy.order import create_newOrder, placeOrder_multithread, cancelAllOrder
from Strategy.model_new import find_all_combination, find_best_pair, print_account_info, print_quote_result, \
    make_some_fake_account_balance, print_all_bids_asks, print_best_bid_ask, create_orders, print_new_orders, \
    print_order_return_info, find_best_sell_orders_we_can_make, find_best_buy_orders_we_can_make, print_new_ordor

from GUI.output import output_Array, output_MarketData, output_newOrder, output_Balance, PATH, output_Response


def market_maker(platform, currency):
    # 1. INPUT
    logging.info("#1. INPUT")
    # 1.1 parameter
    logging.info("#1.1 parameter")

    commodity_cur = currency[0]
    mid_cur = currency[1]
    base_cur = currency[2]

    """
    order1 = {'platform': 'huobi', 'commodity_cur': 'EOS', 'base_cur': 'BTC', 'type': 'buy', 'order': 'limit', 'quantity': 11.0, 'price': 0.0015656}

    order2 = {'platform': platform[0], 'commodity_cur': 'ETH', 'base_cur': 'BTC', 'type': 'buy', 'order': 'limit',
             'quantity': 0.1, 'price': 0.01}

    response = placeOrder_multithread([order1])

    response = cancelAllOrder(platform)
    for res in response:
        logging.info(res)

    return
    
    """
    """
    time_now = timeit.default_timer()
    if time_now - STATIC.time_update > 300:  # hold for 5mins
        account = dict()
        account['trade'] = Account_std(STATIC.PlatformList_valid, 'trade')

        logging.info("Account balance updated with real platform.")
        print_account_info(account['trade'], True)
        # output_Balance(CONST.CurrencyList, account, 'real')

        STATIC.account = account.copy()
        STATIC.time_update = time_now
    else:
        account = STATIC.account.copy()
    """

    account = Account_std(STATIC.PlatformList_valid, 'trade')

    logging.info("Account balance updated with real platform.")
    print_account_info(account, True)

    # 1.2.3 market quote
    # (price_bid, volume_bid, price_ask, volume_ask)
    logging.info("#1.2.3 market quote")

    start = timeit.default_timer()
    pairquote = Quote_multithread_mid(platform, commodity_cur, base_cur, mid_cur, 0)
    stop = timeit.default_timer()
    logging.info('%-10s%-10.2f' % ('Quote', stop - start))

    if stop - start > 2:
        logging.info('Too slow quote')
        return

    STATIC.price[commodity_cur, base_cur] = summarize_Quote(pairquote, commodity_cur, base_cur)
    STATIC.price[base_cur, commodity_cur] = 1.0 / STATIC.price[commodity_cur, base_cur]

    print_account_info(account, False)
    # output_Balance(CONST.CurrencyList, account, 'local')
    print_quote_result(pairquote)

    asks, bids = find_all_combination(pairquote, commodity_cur, mid_cur, base_cur, account)
    print_all_bids_asks(asks, bids)

    if len(asks) == 0 and len(bids) == 0:
        return

    # 2. MODEL
    best_sell_orders_we_can_make = find_best_sell_orders_we_can_make(asks, account)

    best_buy_orders_we_can_make = find_best_buy_orders_we_can_make(bids, account)

    print_new_ordor(best_sell_orders_we_can_make, best_buy_orders_we_can_make)

    if len(best_buy_orders_we_can_make) == 0 and len(best_sell_orders_we_can_make) == 0:
        return

    # 3. ORDER
    logging.info("#3. Limit ORDER")
    start = timeit.default_timer()
    response = placeOrder_multithread(best_sell_orders_we_can_make)
    print_order_return_info(response)
    stop = timeit.default_timer()

    start = timeit.default_timer()
    response = placeOrder_multithread(best_buy_orders_we_can_make)
    print_order_return_info(response)
    stop = timeit.default_timer()

    logging.info('%-10s%-10.2f' % ('Order', stop - start))

    # waiting sec for same one eat my order
    time.sleep(5)

    cansel_list = []
    for item in best_sell_orders_we_can_make:
        cansel_list.append(item['platform'])

    for item in best_buy_orders_we_can_make:
        cansel_list.append(item['platform'])

    response = cancelAllOrder(cansel_list)
    for res in response:
        logging.info(res)

    time.sleep(3)
    account_lastest = Account_std(STATIC.PlatformList_valid, 'trade')
    account_lastest = Account_std(STATIC.PlatformList_valid, 'trade')

    while compare_account(account, account_lastest) is False:
        account_lastest = Account_std(STATIC.PlatformList_valid, 'trade')
        logging.info("account is not same")

    logging.info('---------------------------------account_lastest-------------------------------------')
    print_account_info(account_lastest, True)

    logging.info("#4. sum_commodity")
    sum_commodity = 0
    sum_commodity_ini = 0
    sum_base = 0
    sum_base_ini = 0
    for platf in platform:
        sum_commodity_ini += account[platf].balance[commodity_cur]
        sum_commodity += account_lastest[platf].balance[commodity_cur]
        sum_base_ini += account[platf].balance[base_cur]
        sum_base += account_lastest[platf].balance[base_cur]

    sum_commodity_ini = round(sum_commodity_ini, 8)
    sum_commodity = round(sum_commodity, 8)

    sum_base_ini = round(sum_base_ini, 8)
    sum_base = round(sum_base, 8)

    logging.info("sum_commodity_ini : " + str(sum_commodity_ini))
    logging.info("sum_commodity : " + str(sum_commodity))
    logging.info("")
    logging.info("base_commodity_ini : " + str(sum_base_ini))
    logging.info("base_commodity : " + str(sum_base))
    logging.info("")

    if sum_commodity == sum_commodity_ini or sum_base == sum_base_ini:
        return

    logging.info("#5. Mark_Order")
    pairquote = Quote_multithread_mid(platform, commodity_cur, base_cur, mid_cur, 0)
    print_quote_result(pairquote)
    asks, bids = find_all_combination(pairquote, commodity_cur, mid_cur, base_cur, account_lastest)
    print_all_bids_asks(asks, bids)

    order_new = list()
    if sum_commodity - sum_commodity_ini >= CONST.minsize[commodity_cur]:
        best_bid = None
        for bid in bids:
            if bid[1][0] >= bid[1][1]:
                best_bid = bid
                break
        if best_bid is None:
            return
        amount = min(CONFIG.limit_quantity, round(sum_commodity-sum_commodity_ini, 4),
                     account_lastest[best_bid[5]].balance[best_bid[3]])
        amount = int(amount / CONST.lotsize[commodity_cur]) * CONST.lotsize[commodity_cur]
        order_new.append({'platform': best_bid[5],
                          'commodity_cur': commodity_cur, 'base_cur': base_cur,
                          'type': "sell",
                          'order': "market",
                          'quantity': amount,
                          'price': best_bid[2]})
    elif sum_commodity_ini - sum_commodity >= CONST.minsize[commodity_cur]:
        best_ask = None
        for ask in asks:
            if ask[1][0] >= ask[1][1]:
                best_ask = ask
                break

        if best_ask is None:
            return

        amount = min(CONFIG.limit_quantity, round(sum_commodity_ini - sum_commodity, 4),
                     account_lastest[best_ask[5]].balance[best_ask[4]]/best_ask[2])
        amount = int(amount / CONST.lotsize[commodity_cur]) * CONST.lotsize[commodity_cur]
        order_new.append({'platform': best_ask[5],
                          'commodity_cur': commodity_cur, 'base_cur': base_cur,
                          'type': "buy",
                          'order': "market",
                          'quantity': amount,
                          'price': best_ask[2]})
    else:
        return

    print_new_orders(order_new)
    start = timeit.default_timer()
    response = placeOrder_multithread(order_new)
    print_order_return_info(response)
    stop = timeit.default_timer()

    logging.info('%-10s%-10.2f' % ('Mark_Order', stop - start))

    logging.info("")
    logging.info("6.Summary")
    now = int(time.time())
    if len(best_sell_orders_we_can_make) != 0:
        for item in best_sell_orders_we_can_make:
            logging.info('summary' + str(now) + str(item))

    if len(best_buy_orders_we_can_make) != 0:
        for item in best_buy_orders_we_can_make:
            logging.info('summary' + str(now) + str(item))

    for item in order_new:
        logging.info('summary' + str(now) + str(item))


def compare_account(acc, acc_lastest):
    for plat in acc:
        if plat in acc_lastest:
            continue
        else:
            return False
    return True
